#include <string.h>
#include <sys/param.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/event_groups.h"
#include "esp_system.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "nvs_flash.h"
#include "esp_netif.h"
#include "driver/gpio.h"

#include "lwip/err.h"
#include "lwip/sockets.h"
#include "lwip/sys.h"
#include <lwip/netdb.h>

//#include "iperf.h"

#include "app_wifi.h"
#include "oled.h"



#define TCP_SERVER_ADRESS "192.168.43.1"
#define TCP_SERVER_PORT 5809

int sock_fd = -1;
struct sockaddr_in sera_ddr; //ip地址信息存放的结构体
uint8_t recv_buffer[1024] = {0}; //存放接受到的数据
short int need_reConnect = 1;  //tcp服务器重连标识 1标识需要，0标识不需要
TaskHandle_t x_upShowTask = NULL;


extern char *TAG;
extern EventGroupHandle_t s_wifi_event_group;



void tcp_recvsend_task(void *pvParameters);
void upShow_task(void *pvParameters);


static int show_socket_error_reason(const char *str, int sockfd)
{
    int err = errno;
    if (err != 0) {
        ESP_LOGW(TAG, "%s error, error code: %d, reason: %s", str, err, strerror(err));
    }
    return err;
}

esp_err_t create_tcp_client(){
    ESP_LOGI(TAG, "will connect gateway ssid : %s port:%d",TCP_SERVER_ADRESS, TCP_SERVER_PORT);
    sock_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (sock_fd < 0)
	{
		show_socket_error_reason("create client", sock_fd);
        close(sock_fd);
        return ESP_FAIL;
	}
    sera_ddr.sin_family      = AF_INET;		                    /* 设置地址族为IPv4 */
	sera_ddr.sin_port        = htons (TCP_SERVER_PORT);	           /* 设置地址的端口号信息 */
	sera_ddr.sin_addr.s_addr = inet_addr(TCP_SERVER_ADRESS);	/*　设置IP地址 */
    ESP_LOGI(TAG, "connectting server...");

    int ret = connect(sock_fd, (const struct sockaddr *)&sera_ddr, sizeof(sera_ddr));
    if(ret < 0){
        show_socket_error_reason("create client", sock_fd);
        ESP_LOGE(TAG, "connect failed!");
        close(sock_fd);
        return ESP_FAIL;
    }
    //printf( "Successfully connected\n");
    return ESP_OK; 
}
static void connect_tcp_server(void *pvParameters){
    while(1){
        need_reConnect = 0;
        //等待wifi连接成功
        
        xEventGroupWaitBits(s_wifi_event_group, WIFI_CONNECTED_BIT, false, true, portMAX_DELAY);
        ESP_LOGI(TAG, "start tcp connected");


        TaskHandle_t xtcpRecvTask = NULL;
        vTaskDelay(1000 / portTICK_RATE_MS);
		ESP_LOGI(TAG, "create tcp Client");

        int socket_ret = create_tcp_client();
        if (socket_ret == ESP_FAIL){
			ESP_LOGI(TAG, "create tcp socket error,stop...");
			continue;
		}else{
			ESP_LOGI(TAG, "create tcp socket succeed...");            
			//建立tcp接收数据任务
			if (pdPASS != xTaskCreate(&tcp_recvsend_task, "recv_data", 4096, NULL, 4, &xtcpRecvTask)){
				ESP_LOGI(TAG, "Recv task create fail!");
			}else{
				ESP_LOGI(TAG, "Recv task create succeed!");
			}
        }
        while (1)
        {
            vTaskDelay(3000 / portTICK_RATE_MS);
            if (need_reConnect)
            {
                vTaskDelay(1000 / portTICK_RATE_MS);
                ESP_LOGI(TAG, "reStart create tcp client...");
				//建立client
				int socket_ret = create_tcp_client();
				if (socket_ret == ESP_FAIL){
					ESP_LOGE(TAG, "reStart create tcp socket error,stop...");
					continue;
				}else{
					ESP_LOGI(TAG, "reStart create tcp socket succeed...");
					//重新建立完成，清除标记
					need_reConnect = false;
					//建立tcp接收数据任务
					if (pdPASS != xTaskCreate(&tcp_recvsend_task, "recv_data", 4096, NULL, 4, &xtcpRecvTask)){
						ESP_LOGE(TAG, "reStart Recv task create fail!");
					}else{
						ESP_LOGI(TAG, "reStart Recv task create succeed!");
                    }
                }
            }
        }
    }
}
//xTaskCreate(tcp_recvsend_task, "tcp_client", 4096, NULL, 10, xtcpRecvTask);

void tcp_recvsend_task(void *pvParameters){
    //发送连接成功标识语句
    printf("create tcp recv\n");
    int err = send(sock_fd, "tcp test: hello", strlen("tcp test: hello"), 0);
    if (err < 0) {
        printf( "Error occurred during sending: errno %d", errno);
        return;
        }
        printf("Message sent");
    while (1)
    {
        int len = recv(sock_fd, recv_buffer, sizeof(recv_buffer) - 1, 0);
        if(len > 0){
            recv_buffer[len] = 0; // Null-terminate whatever we received and treat like a string
            printf("Received %d bytes from %s:\n", len, recv_buffer);
            
            //测试将收到的数据发送回去。
            // int err = send(sock_fd, recv_buffer, len, 0);
            // if (err < 0) {
            //     printf( "Error occurred during sending: errno %d", errno);
            //     return;
            // }
            // printf("Message sent");
        }else{
            show_socket_error_reason("tcp_recvsend_task", sock_fd);
            need_reConnect = 1;
            break;
        }
    }
    close(sock_fd);
	need_reConnect = 1;//标记重连
	vTaskDelete(NULL);
}


static void OLED_GPIO_Init(void)
{
    gpio_set_direction(PIN_NUM_CLK, GPIO_MODE_OUTPUT);
    gpio_set_direction(PIN_NUM_MISO, GPIO_MODE_OUTPUT);
	OLED_SCLK_Set();	//
	OLED_SDIN_Set();	//

    OLED_Init();			
	OLED_Clear();
    xTaskCreate(upShow_task, "up_show_task", 4096, NULL, 5, NULL);
}
void upShow_task(void *pvParameters){
	while (1)
	{
        OLED_Clear();  //清空显示
		OLED_ShowString(0,2,recv_buffer);
		vTaskDelay(1000 / portTICK_PERIOD_MS);
		//esp_task_wdt_reset();
	}
    vTaskDelete(NULL);
}



void app_main(){
    wifi_connect_init(); //包含系统存储初始化

    //tcp_client_init();
    OLED_GPIO_Init();
    while (1)
    {
        vTaskDelay(100 / portTICK_RATE_MS);
        if (1/*添加触发代码*/)
        {
            xTaskCreate(connect_tcp_server, "tcp_connect", 4096, NULL, 5, NULL);
            break;
        }
        /* code */
    }
    //xTaskCreate(tcp_client_task, "tck_client", 4096, NULL, 5, NULL);
    //xTaskCreate(函数名, "进程别名", 4096, 函数传入参数, 5, 进程句柄);

}




// static void tcp_client_task(void *pvParameters)
// {
//     int sockfd = -1;    /* 定义一个socket描述符，用来接收打开的socket */
//     int ret = -1;
//     /* 打开一个socket套接字 */
//     sockfd = socket(AF_INET, SOCK_STREAM, 0);
//     if (-1 == sockfd)
// 	{
// 		printf("socket open failure !!! \n");
// 		return ;
// 	}
//     else
//     {
//         struct sockaddr_in sera_ddr = {0};

//         sera_ddr.sin_family = AF_INET;		                    /* 设置地址族为IPv4 */
// 	    sera_ddr.sin_port = htons(5809);	                    /* 设置地址的端口号信息 */
// 	    sera_ddr.sin_addr.s_addr = inet_addr("192.168.43.1");	/*　设置IP地址 */

// 	    ret = connect(sockfd, (const struct sockaddr *)&sera_ddr, sizeof(sera_ddr));
//         if(ret < 0)
//             printf("connect to server failure !!! ret = %d \n",ret);
//         else
//         {
//             printf("connect success.\n");
//             int cnt = 10;
//             while(cnt--)
//             {
//                 ret = send(sockfd, "I am ESP32.", strlen("I am ESP32."), 0);
//                 if(ret < 0)
//                     printf("send err. \n");
//                 else
//                     printf("send ok. \n");
//                 vTaskDelay(2000 / portTICK_PERIOD_MS);   /* 延时2000ms*/
//             }      
//         }          
//         close(sockfd);
//     }
//     vTaskDelete(NULL);
// }

// //创建本地服务器？
// struct sockaddr_in  local_addr;   //初始化本地ip
// local_addr.sin_family      = AF_INET; 
// local_addr.sin_port        = htons(8080);
// local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
// uint8_t res = 0;
// res = bind(sock_fd,(struct sockaddr *)&local_addr,sizeof(local_addr));
// if(res != 0){
//     printf("bind error\n");
// }